﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows;
using System.IO;

namespace DienVu.ContextMenu
{
    enum StyleColor { NA, Red, Green, Blue, Yellow, Normal };

    /// <summary>
    /// BaseStyle for use with MenuItem only
    /// </summary>
    class BaseStyle : System.Windows.Style
    {
        public StyleColor StyleColor { get; private set; }
        public Brush HighlightColor { get; private set; }
        public BaseStyle(StyleColor color = StyleColor.NA)
            : base(typeof(MenuItem))
        {   // Color Style Implement later
            Brush background, foreground, highlightBackground;
            switch (color)
            {
                case StyleColor.NA: background = Brushes.SteelBlue; foreground = Brushes.White; HighlightColor = Brushes.Yellow; break;
                case StyleColor.Red: background = Brushes.Crimson; foreground = Brushes.White; HighlightColor = Brushes.Yellow; break;
                case StyleColor.Green: background = Brushes.LightGreen; foreground = Brushes.Black; HighlightColor = Brushes.Red; break;
                case StyleColor.Blue: background = Brushes.SteelBlue; foreground = Brushes.White; HighlightColor = Brushes.Yellow; break;
                case StyleColor.Yellow: background = Brushes.WhiteSmoke; foreground = Brushes.Black; HighlightColor = Brushes.Red; break;
                case StyleColor.Normal: background = Brushes.White; foreground = Brushes.Black; HighlightColor = Brushes.Red; break;
                default: background = Brushes.White; foreground = Brushes.Black; HighlightColor = Brushes.Blue; break;
            }

            Trigger trigger1 = new Trigger()
            {
                Property = MenuItem.IsHighlightedProperty,
                Value = true,
                Setters = { new Setter(MenuItem.FontSizeProperty, (double)17), new Setter(MenuItem.BackgroundProperty, Brushes.Yellow) } // Why never see RED color ?
            };
            Trigger trigger2 = new Trigger()
            {
                Property = MenuItem.IsEnabledProperty,
                Value = false,
                Setters = { new Setter(MenuItem.ForegroundProperty, Brushes.LightGray), }
            };

            this.Triggers.Add(trigger1);
            this.Triggers.Add(trigger2);
            //this.Setters.Add(new Setter(MenuItem.BorderThicknessProperty, new Thickness(0))); // See if this helpfull ?
            this.Setters.Add(new Setter(MenuItem.BackgroundProperty, background));
            this.Setters.Add(new Setter(MenuItem.ForegroundProperty, foreground));
            this.Setters.Add(new Setter(MenuItem.FontSizeProperty, (double)15));
            this.Setters.Add(new Setter(MenuItem.FontFamilyProperty, new FontFamily("Calibri")));
            this.Setters.Add(new Setter(MenuItem.MarginProperty, new Thickness(-5, 0, 0, 0)));

            this.StyleColor = color;
        }
    }


    //==============================================================================================================================================================//

    /// <summary>
    /// If change HERE, need to Update ToImageSource(Icons Icon) also. And recheck IconFromExtension(string extension) for Extension File only
    /// </summary>
    enum Icons
    {
        NA, UNKNOWN,
        MailOut, MailOutRed, MailOutBlue, MailOutGreen, MailOutYellow,
        Folder, FolderRed, FolderBlue, FolderGreen, FolderYellow, FolderFull, FolderEmpty,
        Search, SearchRed, SearchBlue, SearchGreen, SearchYellow,
        User, UserRed, UserBlue, UserGreen, UserYellow,
        Clock, ClockGreen,
        Cabinet, CabinetGreen,
        Case, CaseGreen,
        Add, AddRed, AddBlue, AddGreen, AddYellow,
        Check, CheckRed, CheckBlue, CheckGreen, CheckYellow,
        PDF, XLS, MSG, PPT, DOC, JPEG, JPG, MDB, ZIP, RAR, CAB, // FILE TYPE : If change here don't forget to update IconFromExtension() Method
        Outlook, Word, Excel, PowerPoint, Access, Msn, Explorer,
        ASEP, HAL, JSA, LOGIQ, WM, UNIT // FOR HALLIBURTON
    };

    class BaseMenu : System.Windows.Controls.ContextMenu
    {
        public BaseMenu(BaseStyle SetStyle = null)
        {
            // Set ContextMenu Behavior
            this.HasDropShadow = true; this.Padding = new Thickness(0); this.Margin = new Thickness(0);

            // Set STYLE for MenuItem
            if (SetStyle == null)
            {
                this.ItemContainerStyle = new BaseStyle(StyleColor.Blue); // Cannot Set BaseMenu Style NA vi cac Item sinh Style tu BaseMenu se deu thanh NA het va OnVisualParentChanged() se lap di lap lai viec Set hoai.
            }
            else
                this.ItemContainerStyle = SetStyle;
        }

        #region AddItem // If you modify here also modify in BaseMenu
        public BaseItem AddItem(string Name, Icons Icon, RoutedEventHandler ItemClickHandler = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, ItemClickHandler, (BaseStyle)this.ItemContainerStyle, Highlight);
            this.Items.Add(item);
            return item;
        }

        public BaseItem AddItem(BaseItem parent, string Name, Icons Icon, RoutedEventHandler ItemClickHandler = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, ItemClickHandler, (BaseStyle)this.ItemContainerStyle, Highlight);
            parent.Items.Add(item);
            return item;
        }

        public BaseItem AddItem(string Name, Icons Icon, string OpenPath = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, OpenPath, (BaseStyle)this.ItemContainerStyle, Highlight);
            this.Items.Add(item);
            return item;
        }

        public BaseItem AddItem(BaseItem parent, string Name, Icons Icon, string OpenPath = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, OpenPath, (BaseStyle)this.ItemContainerStyle, Highlight);
            parent.Items.Add(item);
            return item;
        }

        public void AddItem(BaseItem item)
        {
            item.ItemContainerStyle = this.ItemContainerStyle;
            this.Items.Add(item);
        }
        #endregion
    }

    //==============================================================================================================================================================//

    /// <summary>
    /// BaseItem use for BaseMenu Context
    /// </summary>
    class BaseItem : MenuItem
    {
        public static ImageSource ToImageSource(Icons Icon)
        {
            ImageSource img; DienLib.Converter.WPFBitmapConverter convert = new DienLib.Converter.WPFBitmapConverter();
            switch (Icon)
            {   // Use Uri is shorter. But not sure faster or not ! //uri = new Uri("pack://application:,,,/Resource/Icon/FOLDER-iconB.png"); break;
                case Icons.NA: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpFILEBlank); break;
                case Icons.UNKNOWN: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpUnknown); break;

                case Icons.MailOut: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilMailOutB); break;
                case Icons.MailOutRed: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilMailOutR); break;
                case Icons.MailOutBlue: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilMailOutB); break;
                case Icons.MailOutGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilMailOutG); break;
                case Icons.MailOutYellow: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilMailOutY); break;

                case Icons.Folder: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpFOLDERFull); break;
                case Icons.FolderRed: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilFolderR); break;
                case Icons.FolderBlue: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilFolderB); break;
                case Icons.FolderGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilFolderG); break;
                case Icons.FolderYellow: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilFolderY); break;
                case Icons.FolderFull: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpFOLDERFull); break;
                case Icons.FolderEmpty: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpFOLDERBlank); break;

                case Icons.Search: img = convert.ToImageSource(DienVu.Properties.Resources.ILikeButtonsSearch); break;
                case Icons.SearchRed: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilSearchR); break;
                case Icons.SearchBlue: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilSearchB); break;
                case Icons.SearchGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilSearchG); break;
                case Icons.SearchYellow: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilSearchY); break;

                case Icons.User: img = convert.ToImageSource(DienVu.Properties.Resources.COUPLE_icon); break;
                case Icons.UserRed: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilUserR); break;
                case Icons.UserBlue: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilUserB); break;
                case Icons.UserGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilUserG); break;
                case Icons.UserYellow: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilUserY); break;

                case Icons.Clock: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilClockG); break;
                case Icons.ClockGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilClockG); break;

                case Icons.Cabinet: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilCabinetG); break;
                case Icons.CabinetGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilCabinetG); break;

                case Icons.Case: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilBagG); break;
                case Icons.CaseGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilBagG); break;

                case Icons.Add: img = convert.ToImageSource(DienVu.Properties.Resources.ILikeButtonsNew); break;
                case Icons.AddRed: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilAddR); break;
                case Icons.AddBlue: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilAddB); break;
                case Icons.AddGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilAddG); break;
                case Icons.AddYellow: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilAddY); break;

                case Icons.Check: img = convert.ToImageSource(DienVu.Properties.Resources.CHECK_icon); break;
                case Icons.CheckRed: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilCheckR); break;
                case Icons.CheckBlue: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilCheckG); break;
                case Icons.CheckGreen: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilCheckB); break;
                case Icons.CheckYellow: img = convert.ToImageSource(DienVu.Properties.Resources.OrigamiPencilCheckY); break;

                case Icons.PDF: img = convert.ToImageSource(DienVu.Properties.Resources.JuniorPDF); break;
                case Icons.XLS: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpXLS); break;
                case Icons.MSG: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpMSG); break;
                case Icons.PPT: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpPPT); break;
                case Icons.DOC: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpDOC); break;
                case Icons.JPEG: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpJPG); break;
                case Icons.JPG: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpJPG); break;
                case Icons.MDB: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpMDB); break;
                case Icons.ZIP: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpZIP); break;
                case Icons.RAR: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpRAR); break;
                case Icons.CAB: img = convert.ToImageSource(DienVu.Properties.Resources.PlumpCAB); break;

                case Icons.Outlook: img = convert.ToImageSource(DienVu.Properties.Resources.SoftDimensionOutlook); break;
                case Icons.Word: img = convert.ToImageSource(DienVu.Properties.Resources.SoftDimensionWord); break;
                case Icons.Excel: img = convert.ToImageSource(DienVu.Properties.Resources.SoftDimensionExcel); break;
                case Icons.PowerPoint: img = convert.ToImageSource(DienVu.Properties.Resources.SoftDimensionPowerPoint); break;
                case Icons.Access: img = convert.ToImageSource(DienVu.Properties.Resources.SoftDimensionAccess); break;
                case Icons.Msn: img = convert.ToImageSource(DienVu.Properties.Resources.SoftDimensionMsn); break;
                case Icons.Explorer: img = convert.ToImageSource(DienVu.Properties.Resources.SoftDimensionExplorer); break;

                case Icons.ASEP: img = convert.ToImageSource(DienVu.Properties.Resources.ASEP_icon); break;
                case Icons.HAL: img = convert.ToImageSource(DienVu.Properties.Resources.HAL_icon); break;
                case Icons.JSA: img = convert.ToImageSource(DienVu.Properties.Resources.JSA_icon); break;
                case Icons.LOGIQ: img = convert.ToImageSource(DienVu.Properties.Resources.LOGIQ_icon); break;
                case Icons.WM: img = convert.ToImageSource(DienVu.Properties.Resources.WM_icon); break;
                case Icons.UNIT: img = convert.ToImageSource(DienVu.Properties.Resources.UNIT_icon); break;

                default: img = convert.ToImageSource(DienVu.Properties.Resources.UnknownR); break;
            }
            return img;
        }

        public BaseItem(string Name, Icons Icon, BaseStyle SetStyle = null, bool Highlight = false)
        {
            Init(Name, Icon, null, SetStyle, Highlight);
        }

        public BaseItem(string Name, Icons Icon, string OpenPath, BaseStyle SetStyle = null, bool Highlight = false)
        {
            Init(Name, Icon, (o, e) =>
            {
                if (OpenPath != null)
                    try { System.Diagnostics.Process.Start(OpenPath); }
                    catch (Exception ex) { DienLib.PopUp.PopUpOK.ShowDialog("BaseItem Open File Fail: " + ex.Message, "Fail to Open File | Folder"); }
            }, SetStyle, Highlight);
        }

        public BaseItem(string Name, Icons Icon, RoutedEventHandler ItemClickHandler, BaseStyle SetStyle = null, bool Highlight = false)
        {
            Init(Name, Icon, ItemClickHandler, SetStyle, Highlight);
        }

        private bool isHighlightText;
        private Brush highlightTextColor;
        private void Init(string Name, Icons Icon, RoutedEventHandler ItemClickHandler, BaseStyle SetStyle, bool Highlight)
        {
            // Set STYLE for MenuItem
            BaseStyle style;
            if (SetStyle == null) { style = new BaseStyle(StyleColor.NA); }
            else style = SetStyle;
            this.ItemContainerStyle = style;
            isHighlightText = Highlight; if (isHighlightText) { this.Foreground = highlightTextColor = style.HighlightColor; }

            //this.Padding = new Thickness(0); this.Margin = new Thickness(0);

            // SET HEADER
            this.Header = new TextBlock() { Text = Name, VerticalAlignment = VerticalAlignment.Center };
            //object image = DienVu.Properties.Resources.ResourceManager.GetObject("MAIL-iconB.png");

            // SET ICON
            Image icon = new Image() { Source = ToImageSource(Icon), Width = 32, Height = 32, Margin = new Thickness(1) };
            Border border = new Border() { Background = Brushes.White, /*Padding = new Thickness(2),*/ Child = icon };
            base.Icon = border; this.g_icon = Icon;

            // SET CLICK EVENT HANDLER
            if (ItemClickHandler != null) this.Click += ItemClickHandler; //this.AddHandler(MenuItem.ClickEvent, ItemClickHandler);
        }

        /*protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
        {
            if (isHighlightText) this.Foreground = highlightTextColor;
            base.OnMouseLeave(e);
        }

        protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
        {
            if (isHighlightText) this.Foreground = Brushes.Yellow;
            base.OnMouseEnter(e);
        }*/

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.Property == IsHighlightedProperty)
            {
                if (IsHighlighted) { if (isHighlightText) this.Foreground = Brushes.Yellow; }
                else { if (isHighlightText) this.Foreground = highlightTextColor; }
            }
            base.OnPropertyChanged(e);
        }

        protected override void OnVisualParentChanged(DependencyObject oldParent)
        {
            base.OnVisualParentChanged(oldParent);
            if ((this.ItemContainerStyle as BaseStyle).StyleColor == StyleColor.NA) this.ItemContainerStyle = (this.Parent as ItemsControl).ItemContainerStyle;
        }

        protected override void OnSubmenuOpened(RoutedEventArgs e)
        {
            base.OnSubmenuOpened(e);
            /*MenuItem subitem = this.Items[0] as MenuItem;
            MenuItem item = subitem.Parent as MenuItem;
            System.Windows.Controls.ContextMenu menu2 = item.Parent as System.Windows.Controls.ContextMenu;
            Thickness th = menu2.Padding;

            System.Windows.Controls.ContextMenu menu = (this.Parent as System.Windows.Controls.ContextMenu);
            menu.Padding = new Thickness(0);*/
        }


        private Icons g_icon;
        public Icons Icons
        {
            get { return g_icon; }
            set { ((base.Icon as Border).Child as Image).Source = ToImageSource(value); g_icon = value; }
        }

        #region AddItem // If you modify here also modify in BaseMenu
        public BaseItem AddItem(string Name, Icons Icon, RoutedEventHandler ItemClickHandler = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, ItemClickHandler, (BaseStyle)this.ItemContainerStyle, Highlight);
            this.Items.Add(item);
            return item;
        }

        public BaseItem AddItem(BaseItem parent, string Name, Icons Icon, RoutedEventHandler ItemClickHandler = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, ItemClickHandler, (BaseStyle)this.ItemContainerStyle, Highlight);
            parent.Items.Add(item);
            return item;
        }

        public BaseItem AddItem(string Name, Icons Icon, string OpenPath = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, OpenPath, (BaseStyle)this.ItemContainerStyle, Highlight);
            this.Items.Add(item);
            return item;
        }

        public BaseItem AddItem(BaseItem parent, string Name, Icons Icon, string OpenPath = null, bool Highlight = false)
        {
            BaseItem item = new BaseItem(Name, Icon, OpenPath, (BaseStyle)this.ItemContainerStyle, Highlight);
            parent.Items.Add(item);
            return item;
        }

        public void AddItem(BaseItem item)
        {
            item.ItemContainerStyle = this.ItemContainerStyle;
            this.Items.Add(item);
        }
        #endregion
    }


    //==============================================================================================================================================================//


    /// <summary>
    /// FileItem with FileName will be display in context menu. When activate will search & show drop down. When deactivate will refresh if not found will auto delete.
    /// Allow you binding callback with object pass in is "that file" for further action
    /// </summary>
    class FileItem : BaseItem
    {
        public static Icons IconFromExtension(string extension)
        {
            switch (extension.Trim().ToLower())
            {
                case ".xls": return Icons.XLS;
                case ".xlsx": return Icons.XLS;
                case ".xlsm": return Icons.XLS;
                case ".pdf": return Icons.PDF;
                case ".ppt": return Icons.PPT;
                case ".pptx": return Icons.PPT;
                case ".pptm": return Icons.PPT;
                case ".doc": return Icons.DOC;
                case ".docx": return Icons.DOC;
                case ".docm": return Icons.DOC;
                case ".txt": return Icons.DOC;
                case ".jpeg": return Icons.JPEG;
                case ".jpg": return Icons.JPG;
                case ".accdb": return Icons.MDB;
                case ".mdb": return Icons.MDB;
                case ".msg": return Icons.MSG;
                case ".zip": return Icons.ZIP;
                case ".rar": return Icons.RAR;
                case ".cab": return Icons.CAB;
                default: return Icons.UNKNOWN;
            }
        }

        public FileInfo FileInfo { get; set; } // Consider to use Tag instead
        public FileItem(FileInfo FileInfo, string overrideName = null, Icons overrideIcon = Icons.NA, bool Highlight = false)
            : base(overrideName == null ? FileInfo.Name : overrideName, overrideIcon == Icons.NA ? IconFromExtension(FileInfo.Extension) : overrideIcon, Highlight: Highlight)
        {
            this.FileInfo = FileInfo;
            ((base.Icon as Border).Child as Image).Source = new DienLib.Converter.WPFBitmapConverter().ToImageSource(System.Drawing.Icon.ExtractAssociatedIcon(this.FileInfo.FullName));
        }
    }


    //==============================================================================================================================================================//


    /// <summary>
    /// FolderItem use specially for Folder during ContextMenu
    /// </summary>
    class FolderItem : BaseItem
    {
        const string LOADING = "Loading ...";
        const string EMPTY = "Empty ...";
        private bool g_overridedIcon = false;
        public bool IsOverrideIcon { get { return g_overridedIcon; } }
        public DirectoryInfo FolderInfo { get; set; } // Consider to use Tag instead
        public FolderItem(DirectoryInfo FolderInfo, string overrideName = null, Icons overrideIcon = Icons.Folder, bool Highlight = false)
            : base(overrideName == null ? FolderInfo.Name : overrideName, overrideIcon, Highlight: Highlight)
        {
            this.FolderInfo = FolderInfo;
            if (!this.FolderInfo.Exists) return;
            // If Exist
            this.Items.Add(new BaseItem(LOADING, Icons.NA));
            if (overrideIcon != Icons.Folder) this.g_overridedIcon = true;
        }

        protected override void OnSubmenuOpened(RoutedEventArgs e)
        {   // Load All Sub Folder
            // Iterate all Files & Folders of this Folder
            if (!this.FolderInfo.Exists) return;

            foreach (FileInfo file in this.FolderInfo.GetFiles())
            {   // Interate FILEs
                this.Items.Add(new FileItem(file));
            }

            foreach (DirectoryInfo folder in this.FolderInfo.GetDirectories())
            {   // Interate FOLDERs
                if (folder.GetFileSystemInfos().Length > 0)
                {   // Folder is not EMPTY
                    FolderItem item = new FolderItem(folder); if (!item.IsOverrideIcon) item.Icons = Icons.FolderFull;
                    this.Items.Add(item);
                }
                else
                {   // Folder is EMPTY
                    FolderItem item = new FolderItem(folder); if (!item.IsOverrideIcon) item.Icons = Icons.FolderEmpty;
                    this.Items.Add(item);
                }
            }

            if (this.Items.Count > 1) this.Items.RemoveAt(0); // Remove the "Loading ..."
            else this.Items[0] = new BaseItem(EMPTY, Icons.NA);

            base.OnSubmenuOpened(e);
        }

        protected override void OnSubmenuClosed(RoutedEventArgs e)
        {   // Delete All Sub Folder
            this.Items.Clear(); this.Items.Add(new BaseItem(LOADING, Icons.NA));
            base.OnSubmenuClosed(e);
        }
    }
}
